/******************************************************************************
 * Copyright 2022 The Airos Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#pragma once

#include <sys/time.h>

#include <deque>
#include <map>
#include <memory>
#include <string>
#include <vector>

#include "air_middleware_component.h"
#include "air_service/modules/perception-usecase/proto/roi_lane.pb.h"
#include "air_service/modules/perception-usecase/proto/roi_points.pb.h"
#include "air_service/modules/perception-usecase/usecase/base/runner.h"
#include "air_service/modules/perception-usecase/usecase/common/timer.h"
#include "air_service/modules/perception-usecase/usecase/common/vec2d.h"
#include "cyberrt_component.h"

#ifdef USE_VIZ
#include "air_service/modules/perception-usecase/visualization/visualization_internal.h"
#endif

namespace airos {
namespace perception {
namespace usecase {

#define USECASE_COMPONENT AIROS_COMPONENT_CLASS_NAME(UseCaseComponent)

class USECASE_COMPONENT : public airos::middleware::ComponentAdapter<
                              airos::perception::PerceptionObstacles> {
 public:
  USECASE_COMPONENT() : seq_num_(0) {}
  ~USECASE_COMPONENT() = default;

  bool Init() override;
  bool Proc(const std::shared_ptr<const airos::perception::PerceptionObstacles>&
                perception_obstacles) override;

 private:
  void PostProc(std::shared_ptr<airos::usecase::EventOutputResult> output_event,
                const double& us);
  double GetCurrentTimeMicroseconds() {
    struct timeval tv;
    gettimeofday(&tv, nullptr);
    return tv.tv_sec * 1000000 + tv.tv_usec;
  }

 private:
  bool is_usecase_ = true;
  uint32_t seq_num_;
  airos::usecase::roi::LaneParam mini_map_params_;
  std::string channel_v2x_usecase_;
  // for Runner
  std::unique_ptr<Runner> events_runner_;
  std::shared_ptr<std::vector<std::string>> events_pipeline_;
  Timer timer_;

#ifdef USE_VIZ
  std::shared_ptr<UsecaseVisualizer> usecase_visualizer_;
#endif
};

REGISTER_AIROS_COMPONENT_CLASS(UseCaseComponent,
                               airos::perception::PerceptionObstacles);

}  // end of namespace usecase
}  // end of namespace perception
}  // end of namespace airos
